﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Timers;
using System.ComponentModel;
using FinPlusInterfaces;
using FinPlusAssembler;

namespace FinPlusCompCore
{
    public class FinPlusServiceManager : FinPlusComponent 
    {
        [State(Test = true)]
        public override bool IsValid { get; set; }
        public override IPods Adapter { get { return _adapter; } }

        private IServiceConn _conn;
        private IPods _adapter;
        private Timer _timer;
        private static int _id;

        //construct
        public FinPlusServiceManager(int refresh = 5000)
        {
            IsValid = true;
            _conn = IOC.New<IServiceConn>();
            _adapter = IOC.New<IPods>();
            _timer = new Timer(refresh) { Enabled = true };
            _timer.Elapsed += Info_Refresh;
            Refresh();
        }

        //common control interface 
        public override void CmdExecute(IPod command)
        {
            try
            {
                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.Refresh: Refresh(); break;
                    case Cmds.Stop: Stop(command["Tag"].ToString());  break;
                    case Cmds.Start: Start(command["Tag"].ToString()); break;
                    default: throw new Exception(string.Format("cmd not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = Level.Error.Log(Id, Config, e.Message, e);
            }
        }

        public override void Dispose()  { }

        //private
        private void Refresh()
        {
            _timer.Stop();
            try
            {
                var infos = _conn.Infos();
                var time = DateTime.Now;
              
                foreach (var info in infos.Values)
                {
                    var service = _adapter.First("Name='Guid' And Value='" + info["Guid"].ToString() + "'");
                    if (service == null)
                    {
                        service = info.Clone(_id++);
                        service.Get<DateTime>("Poll", time);
                        service.Get<bool>("Run", true, Run_Event);
                        _adapter.Update(service, ChangeType.New);
                    }
                    else
                    {
                        service.Get("Run").Update(info.Get("Started").Object);
                        service.Get("Started").Update(info.Get("Started").Object);
                        service.Get("Completed").Update(info.Get("Completed").Object);
                        service.Get("NumConn").Update(info.Get("NumConn").Object);
                        service.Get("Poll").Update(time);
                    }
                }
            }
            catch (Exception e)
            {
                IsValid = Level.Error.Log("failed to refresh service", e);
            }

            _timer.Start();
        }

        private void Stop(string id)
        {
            try
            {
                _conn.Stop(_adapter[int.Parse(id)].Get("ServiceKey").ToString());
            }
            catch (Exception e)
            {
                IsValid = Level.Error.Log(string.Format("failed to stop service {0}", id), e);
            }
        }

        private void Start(string id)
        {
            try
            {
                _conn.Start(_adapter[int.Parse(id)].Get("ServiceKey").ToString());
            }
            catch (Exception e)
            {
                IsValid = Level.Error.Log(string.Format("failed to start service {0}", id), e);
            }
        }

        //cmds
        private enum Cmds { Refresh, Start, Stop }

        //private
        private void Info_Refresh(object sender, ElapsedEventArgs e){CmdRouter(Cmds.Refresh.ToString());}

        private void Run_Event(object sender, PropertyChangedEventArgs e)
        {
            var run = (IBean)sender;
            CmdRouter((bool)run.Object ? Cmds.Start.ToString():Cmds.Stop.ToString(), run.Id.ToString());
        }
    }
}
